home *** CD-ROM | disk | FTP | other *** search
/ Developer CD Series 1993…ch: Other People's Memory / ADC Developer CD (1993-03) (''Other People's Memory'')_iso / Dev.CD Mar 93.iso / Development Platforms / CSMP Digests / csmp-v1-027.txt < prev    next >
Encoding:
Text File  |  1992-11-18  |  44.8 KB  |  1,300 lines  |  [TEXT/MPS ]

  1. C.S.M.P. Digest             Sat, 21 Mar 92       Volume 1 : Issue 27
  2.  
  3. Today's Topics:
  4.  
  5.      Finding available fonts
  6.     Q: Eliminating clicks when playing sampled sounds
  7.     Software Locking for Word 4D
  8.     DirectorOwner owns DialogDirector and crashes (Think C/TCL)
  9.  
  10.  
  11. The Comp.Sys.Mac.Programmer Digest is moderated by Michael A. Kelly.
  12.  
  13. These digests are available (by using FTP, account anonymous, your email
  14. address as password) in the pub/mac/csmp-digest directory on ftp.cs.uoregon.
  15. edu (try skinner.cs.uoregon.edu if that doesn't work).  This is also the home
  16. of the comp.sys.mac.programmer Frequently Asked Questions list.
  17.  
  18. These digests are also available via email.  Just send a note saying that you
  19. want to be on the digest mailing list to mkelly@cs.uoregon.edu, and you will
  20. automatically receive each new digest as it is created.
  21.  
  22. The articles in these digests are taken directly from comp.sys.mac.programmer.
  23. They are not edited; all articles included in this digest are in their original
  24. posted form.  The only articles that are -not- included in these digests are
  25. those which didn't receive any replies (except those that give information
  26. rather than ask a question).  All replies to each article are concatenated
  27. onto the original article in the order in which they were received.  Article
  28. threads are not added to the digests until the last article added to the
  29. thread is at least one month old (this is to ensure that the thread is dead
  30. before adding it to the digests).
  31.  
  32. Send administrative mail to mkelly@cs.uoregon.edu.
  33.  
  34. -------------------------------------------------------
  35.  
  36. From: jpugh@apple.com (Jon Pugh)
  37. Subject:  Finding available fonts
  38. Date: 20 Jan 92 21:17:23 GMT
  39. Organization: Apple Co.
  40.  
  41. In article <1992Jan17.150406@wilbury.cs.Virginia.EDU>, rad2r@wilbury.cs.Virginia.EDU (Robert DeLine) writes:
  42. > What I'm looking for is a way from within a program to find out
  43. > which font families are currently available.  I've noticed that
  44. > many applications look up this information, so I know it must be
  45. > possible. Perhaps I should mention that the final destination for
  46. > this list is not a menu.  This is easy, right?
  47. > Rob DeLine
  48. > deline@Virginia.EDU
  49.  
  50. Fonts are stored in several resources.  In theory every font family should have a FOND 
  51. resource and a list of them would suffice.  The actual font faces are stored as FONT and 
  52. NFNT resources with TrueType outlines stored as sfnt resources.
  53.  
  54. Good luck,
  55.  
  56. Jon
  57.  
  58.  
  59.  
  60. - -------------------------
  61.  
  62. From: wdh@well.sf.ca.us (Bill Hofmann)
  63. Subject:  Finding available fonts
  64. Date: 28 Jan 92 17:39:12 GMT
  65. Organization: Flashpoint
  66.  
  67. jpugh@apple.com (Jon Pugh) writes:
  68.  
  69. >In article <1992Jan17.150406@wilbury.cs.Virginia.EDU>, rad2r@wilbury.cs.Virginia.EDU (Robert DeLine) writes:
  70. >> 
  71. >> What I'm looking for is a way from within a program to find out
  72. >> which font families are currently available.  I've noticed that
  73. >> many applications look up this information, so I know it must be
  74. >> possible. Perhaps I should mention that the final destination for
  75. >> this list is not a menu.  This is easy, right?
  76. >Fonts are stored in several resources.  In theory every font family should have a FOND 
  77. >resource and a list of them would suffice.  The actual font faces are stored as FONT and 
  78. >NFNT resources with TrueType outlines stored as sfnt resources.
  79. >Good luck,
  80. >Jon
  81.  
  82. Actually, the easiest, AND recommended, way to get the fonts in the system
  83. is to create a menu.  So:
  84. {
  85.     MenuHandle    faux;
  86.     Str255        fontName;
  87.     short        fontNum;
  88.     short        i, numFonts;
  89.  
  90.     faux = NewMenu("\pFaunt");
  91.     AddResMenu(faux, 'FONT');    /* of course, check for NIL */
  92.     numFonts = CountMItems(faux);
  93.     for (i = 1; i <= numFonts; i++)
  94.     {
  95.         GetItem(faux, i, fontName);
  96.         GetFNum(fontName, &fontNum);
  97.         /* do what you will with fontNum */
  98.     }
  99.     DisposMenu(faux);
  100. }
  101. The reason is that every time they muck with the system they'll add and
  102. modify font resource types, but they HAVE to guarantee that AddResMenu
  103. will always work, so your program will ALWAYS get the current list of
  104. fonts, be they bitmap FONT, bitmap NFNT, sfnt, or whatever.
  105.  
  106. -Bill Hofmann
  107.  
  108.  
  109.  
  110. - -------------------------
  111.  
  112. From: nerm@apple.com (Dean Yu)
  113. Subject:  Finding available fonts
  114. Date: 31 Jan 92 23:21:55 GMT
  115. Organization: Apple Computer, Inc.
  116.  
  117. In article <29685@well.sf.ca.us>, wdh@well.sf.ca.us (Bill Hofmann) writes:
  118. > jpugh@apple.com (Jon Pugh) writes:
  119. > >In article <1992Jan17.150406@wilbury.cs.Virginia.EDU>, rad2r@wilbury.cs.Virginia.EDU (Robert DeLine) writes:
  120. > >> 
  121. > >> What I'm looking for is a way from within a program to find out
  122. > >> which font families are currently available.  I've noticed that
  123. > >> many applications look up this information, so I know it must be
  124. > >> possible. Perhaps I should mention that the final destination for
  125. > >> this list is not a menu.  This is easy, right?
  126. > >Fonts are stored in several resources.  In theory every font family should have a FOND 
  127. > >resource and a list of them would suffice.  The actual font faces are stored as FONT and 
  128. > >NFNT resources with TrueType outlines stored as sfnt resources.
  129. > >Good luck,
  130. > >Jon
  131. > Actually, the easiest, AND recommended, way to get the fonts in the system
  132. > is to create a menu.  So:
  133. > {
  134. >     MenuHandle    faux;
  135. >     Str255        fontName;
  136. >     short        fontNum;
  137. >     short        i, numFonts;
  138. >     faux = NewMenu("\pFaunt");
  139. >     AddResMenu(faux, 'FONT');    /* of course, check for NIL */
  140.                      ^^^^
  141.  
  142.   Just to be nitpicky, you should use AddResMenu(faux, 'FOND') to access
  143. available fonts through the font families they belong to.
  144.  
  145.   -- Dean Yu
  146.      Blue Meanie, Negative Ethnic Role Model, Window Cleaner,
  147.       Skanky Hack Consultant, etc.
  148.      Apple Computer, Inc.
  149.      blah blah blah blah blah...
  150.  
  151.  
  152.  
  153. - -------------------------
  154.  
  155. From: wdh@well.sf.ca.us (Bill Hofmann)
  156. Subject:  Finding available fonts
  157. Date: 28 Jan 92 17:39:12 GMT
  158. Organization: Flashpoint
  159.  
  160. jpugh@apple.com (Jon Pugh) writes:
  161.  
  162. >In article <1992Jan17.150406@wilbury.cs.Virginia.EDU>, rad2r@wilbury.cs.Virginia.EDU (Robert DeLine) writes:
  163. >> 
  164. >> What I'm looking for is a way from within a program to find out
  165. >> which font families are currently available.  I've noticed that
  166. >> many applications look up this information, so I know it must be
  167. >> possible. Perhaps I should mention that the final destination for
  168. >> this list is not a menu.  This is easy, right?
  169. >Fonts are stored in several resources.  In theory every font family should have a FOND 
  170. >resource and a list of them would suffice.  The actual font faces are stored as FONT and 
  171. >NFNT resources with TrueType outlines stored as sfnt resources.
  172. >Good luck,
  173. >Jon
  174.  
  175. Actually, the easiest, AND recommended, way to get the fonts in the system
  176. is to create a menu.  So:
  177. {
  178.     MenuHandle    faux;
  179.     Str255        fontName;
  180.     short        fontNum;
  181.     short        i, numFonts;
  182.  
  183.     faux = NewMenu("\pFaunt");
  184.     AddResMenu(faux, 'FONT');    /* of course, check for NIL */
  185.     numFonts = CountMItems(faux);
  186.     for (i = 1; i <= numFonts; i++)
  187.     {
  188.         GetItem(faux, i, fontName);
  189.         GetFNum(fontName, &fontNum);
  190.         /* do what you will with fontNum */
  191.     }
  192.     DisposMenu(faux);
  193. }
  194. The reason is that every time they muck with the system they'll add and
  195. modify font resource types, but they HAVE to guarantee that AddResMenu
  196. will always work, so your program will ALWAYS get the current list of
  197. fonts, be they bitmap FONT, bitmap NFNT, sfnt, or whatever.
  198.  
  199. -Bill Hofmann
  200.  
  201.  
  202.  
  203. - -------------------------
  204.  
  205. From: nerm@apple.com (Dean Yu)
  206. Subject:  Finding available fonts
  207. Date: 31 Jan 92 23:21:55 GMT
  208. Organization: Apple Computer, Inc.
  209.  
  210. In article <29685@well.sf.ca.us>, wdh@well.sf.ca.us (Bill Hofmann) writes:
  211. > jpugh@apple.com (Jon Pugh) writes:
  212. > >In article <1992Jan17.150406@wilbury.cs.Virginia.EDU>, rad2r@wilbury.cs.Virginia.EDU (Robert DeLine) writes:
  213. > >> 
  214. > >> What I'm looking for is a way from within a program to find out
  215. > >> which font families are currently available.  I've noticed that
  216. > >> many applications look up this information, so I know it must be
  217. > >> possible. Perhaps I should mention that the final destination for
  218. > >> this list is not a menu.  This is easy, right?
  219. > >Fonts are stored in several resources.  In theory every font family should have a FOND 
  220. > >resource and a list of them would suffice.  The actual font faces are stored as FONT and 
  221. > >NFNT resources with TrueType outlines stored as sfnt resources.
  222. > >Good luck,
  223. > >Jon
  224. > Actually, the easiest, AND recommended, way to get the fonts in the system
  225. > is to create a menu.  So:
  226. > {
  227. >     MenuHandle    faux;
  228. >     Str255        fontName;
  229. >     short        fontNum;
  230. >     short        i, numFonts;
  231. >     faux = NewMenu("\pFaunt");
  232. >     AddResMenu(faux, 'FONT');    /* of course, check for NIL */
  233.                      ^^^^
  234.  
  235.   Just to be nitpicky, you should use AddResMenu(faux, 'FOND') to access
  236. available fonts through the font families they belong to.
  237.  
  238.   -- Dean Yu
  239.      Blue Meanie, Negative Ethnic Role Model, Window Cleaner,
  240.       Skanky Hack Consultant, etc.
  241.      Apple Computer, Inc.
  242.      blah blah blah blah blah...
  243.  
  244.  
  245.  
  246. ---------------------------
  247.  
  248. From: pwinkler@netcom.COM (Paul Winkler)
  249. Subject: Q: Eliminating clicks when playing sampled sounds
  250. Date: 21 Jan 92 00:24:58 GMT
  251. Organization: Netcom - Online Communication Services  (408 241-9760 guest)
  252.  
  253.  
  254. I have tried everything I can think of, so I turn to the collective
  255. net.wisdom.
  256.  
  257. I am writing an application that plays sounds that are stored on disk.  
  258. The sound samples are interleaved with other data on the disk so 
  259. SndFilePlay() is not an option for me.  The data is stored 800 
  260. bytes at a time, and the data was sampled at 8000 samples/sec (exactly).  
  261. I am running a Mac IIci and IIfx running Sys 6.0.7.
  262.  
  263. I have tried using SndDoCommand() and SndPlayDoubleBuffer() after extracting
  264. the data from the disk and the sound plays fine, but it has clicks in 
  265. the audio equivalent to the 'group' rate (ie, 10 groups of 800 bytes each
  266. played a second == clicks a second).  I am trying to get the sound to 
  267. play without the clicks.
  268.  
  269. I thought that the disk access (interrupts or the like) may have been the 
  270. problem, but I broke out a simple application that just has a quiet pattern 
  271. (or a one frequency tone) in the sound buffers, and there is no sound...  
  272. except for the clicks.  Usually there are clicks but sometimes not.  This
  273. simple application is set up with SndPlayDoubleBuffer() and is almost identical
  274. to the example in Ch 22 of Vol VI.  (I can post or forward the code to any kind
  275. soul who thinks they can help.)
  276.  
  277. It is advertised in the tech literature that the Mac will play continuous 
  278. sound.  Am I being unreasonable to assume that it can/will play it 
  279. 'seamlessly'?  Is it related to the fact that I am using a 'non-standard'
  280. sample rate?  (I don't think so, since I use standard rates with my
  281. simple program.)  How does QuickTime do it?  Does it just play long frames, 
  282. so that the inter-frame click is less noticable?  Am I missing something?
  283.  
  284. Any ideas, suggestions, or pointers to RTFM (Read The F***ing Manual)
  285. via email or post will be greatly appreciated.
  286.  
  287. Thanks for your time,
  288.  
  289. Paul Winkler
  290. pwinkler@netcom.com
  291.  
  292.  
  293.  
  294. - -------------------------
  295.  
  296. From: ldo@waikato.ac.nz (Lawrence D'Oliveiro, Waikato University)
  297. Subject:  Q: Eliminating clicks when playing sampled sounds
  298. Date: 21 Jan 92 03:56:46 GMT
  299. Organization: University of Waikato, Hamilton, New Zealand
  300.  
  301. In article <1992Jan21.002458.1464pwinkler@netcom.COM>, pwinkler@netcom.COM
  302. (Paul Winkler) complains about clicks in playing sound data in 800-byte
  303. chunks on a machine with the Apple Sound Chip.
  304.  
  305. As I recall, the ASC has internal buffers somewhat larger than this (more
  306. like 2K, I think). The clicks may be due to the chip being turned off
  307. when the buffer goes empty, and then turning on again for the next lot.
  308. Have you tried sending larger-sized chunks to SndDoCommand? Try buffering
  309. your data in memory and feeding it to SndDoCommand in chunks of at least 2K.
  310.  
  311. I understand QuickTime plays all its sound using straight SndDoCommand calls.
  312.  
  313. Lawrence D'Oliveiro                       fone: +64-7-856-2889
  314. Computer Services Dept                     fax: +64-7-838-4066
  315. University of Waikato            electric mail: ldo@waikato.ac.nz
  316. Hamilton, New Zealand    37^ 47' 26" S, 175^ 19' 7" E, GMT+13:00
  317. The only thing to do with good advice is to pass it on. It is never of
  318. any use to oneself.                                  -- Oscar Wilde
  319.  
  320.  
  321.  
  322. - -------------------------
  323.  
  324. From: pwinkler@netcom.COM (Paul Winkler)
  325. Subject:  Q: Eliminating clicks when playing sampled sounds
  326. Date: 21 Jan 92 06:59:21 GMT
  327. Organization: Netcom - Online Communication Services  (408 241-9760 guest)
  328.  
  329. Thanks for the response, but alas, I have tried the test program with 
  330. buffers as large as 4K, and it just makes the clicks less frequent
  331. (two per second versus 10 per second).  
  332.  
  333. Any other ideas?
  334.  
  335. Thanks again
  336.  
  337. Paul
  338. pwinkler@netcom.com
  339.  
  340.  
  341.  
  342. - -------------------------
  343.  
  344. From: REEKES@applelink.apple.com (Jim Reekes)
  345. Subject:  Q: Eliminating clicks when playing sampled sounds
  346. Date: 22 Jan 92 22:13:28 GMT
  347. Organization: Apple Computer, Inc.
  348.  
  349. In article <1992Jan21.002458.1464pwinkler@netcom.COM>, pwinkler@netcom.COM (Paul Winkler) writes:
  350. > I am writing an application that plays sounds that are stored on disk.  
  351. > The sound samples are interleaved with other data on the disk so 
  352. > SndFilePlay() is not an option for me.  The data is stored 800 
  353. > bytes at a time, and the data was sampled at 8000 samples/sec (exactly).  
  354. > I am running a Mac IIci and IIfx running Sys 6.0.7.
  355. > I have tried using SndDoCommand() and SndPlayDoubleBuffer() after extracting
  356. > the data from the disk and the sound plays fine, but it has clicks in 
  357. > the audio equivalent to the 'group' rate (ie, 10 groups of 800 bytes each
  358. > played a second == clicks a second).  I am trying to get the sound to 
  359. > play without the clicks.
  360. > I thought that the disk access (interrupts or the like) may have been the 
  361. > problem, but I broke out a simple application that just has a quiet pattern 
  362. > (or a one frequency tone) in the sound buffers, and there is no sound...  
  363. > except for the clicks.  Usually there are clicks but sometimes not.  This
  364. > simple application is set up with SndPlayDoubleBuffer() and is almost identical
  365. > to the example in Ch 22 of Vol VI.  (I can post or forward the code to any kind
  366. > soul who thinks they can help.)
  367. > It is advertised in the tech literature that the Mac will play continuous 
  368. > sound.  Am I being unreasonable to assume that it can/will play it 
  369. > 'seamlessly'?  Is it related to the fact that I am using a 'non-standard'
  370. > sample rate?  (I don't think so, since I use standard rates with my
  371. > simple program.)  How does QuickTime do it?  Does it just play long frames, 
  372. > so that the inter-frame click is less noticable?  Am I missing something?
  373.  
  374.  
  375. Don't bother attempting to use SndPlayDoubleBuffer.  The only 
  376. reason SndPlayDoubleBuffer was written was to support 
  377. SndStartFilePlay.  When you call SndStartFilePlay you are using the 
  378. double buffer routines.  By using SndPlayDoubleBuffer directly, 
  379. you're only making it harder on yourself and you'll gain nothing 
  380. that cannot be accomplished by using SndDoCommand and the 
  381. bufferCmd.
  382.  
  383. One reason which would cause clicks when the sound chip is turned 
  384. on or off.  It's that the previous buffer of data wasn't at a zero 
  385. crossing.  When the chip is turned on, it has a problem of clicking 
  386. if the internal buffer contains some sampled data that isn't 
  387. silence.  If you add some silence to the end of all your buffer it 
  388. should remove the clicking.  Add about 512 bytes of 0x80 to then 
  389. end of your sampled sound.  Also, you should ramp the sounds to 
  390. silence and not just cut them off.  All of this information is 
  391. specific to the point when you call SndNewChannel and 
  392. SndDisposeChannel.
  393.  
  394. As far as using small buffers to create a continuous sound, 
  395. QuickTime simply uses the bufferCmd to queue all of its sound 
  396. buffers.  There's no magic involved, and no undocumented secret 
  397. tricks.  The Sound Manager will attempt to butt-splice the new 
  398. buffer to the older one to avoid unnecessary padding of silence, 
  399. which will be necessary when rate converting to the hardware's 
  400. output rate (22k).  If there is multiple sound channels, then there 
  401. will be some amount of gaps in the sound at buffer endings.  Also, 
  402. 800 bytes is pretty small.  You should try to at least create 
  403. buffers of 2k or larger.  Other than that I'd say it's something to 
  404. do with you data and your code.  OK, well that's everything but it 
  405. works for me so it must be something unique about your 
  406. configuration.
  407.  
  408. - -----------------------------------------------------------------
  409. Jim Reekes, E.O.             |     Macintosh Toolbox Engineering
  410.                              |          Sound Manager Expert
  411. Apple Computer, Inc.         | All opinions expressed are mine, and
  412. 20525 Mariani Ave. MS: 81-EQ |  do not necessarily represent those
  413. Cupertino, CA 95014          |  of my employer, Apple Computer Inc.
  414.  
  415.  
  416.  
  417. - -------------------------
  418.  
  419. From: eacj@theory.TC.Cornell.EDU (Julian Vrieslander)
  420. Subject:  Q: Eliminating clicks when playing sampled sounds
  421. Date: 23 Jan 92 23:05:59 GMT
  422. Organization: Cornell Theory Center
  423.  
  424. In article <19414@goofy.Apple.COM> REEKES@applelink.apple.com (Jim Reekes) writes:
  425. >One reason which would cause clicks when the sound chip is turned 
  426. >on or off.  It's that the previous buffer of data wasn't at a zero 
  427. >crossing.  When the chip is turned on, it has a problem of clicking 
  428. >if the internal buffer contains some sampled data that isn't 
  429. >silence.  If you add some silence to the end of all your buffer it 
  430. >should remove the clicking.  Add about 512 bytes of 0x80 to then 
  431. >end of your sampled sound.  Also, you should ramp the sounds to 
  432. >silence and not just cut them off.  All of this information is 
  433. >specific to the point when you call SndNewChannel and 
  434. >SndDisposeChannel.
  435.  
  436. This recipe will eliminate one source of clicks, but it is still possible
  437. to get clicks from another mechanism, at least on some Macs.
  438.  
  439. I can create a long waveform containing *only* silent samples (0x80), and
  440. when I play it repeatedly, sometimes there will be clicks produced.  If I
  441. use Farallon's SoundEdit, the moving waveform cursor gives a rough indication
  442. of where in the buffer the click is occurring.  I think it is usually at
  443. the beginning of the buffer, but I am not certain that the clicks are
  444. not coming at other points.  This clicking has been observed with several
  445. programs, including some I wrote myself.  I use the simplest SoundMgr call:
  446. SndPlay(NULL, theSnd, TRUE).   
  447.  
  448. This clicking has been observed on our Mac II, and (I think) on our Mac
  449. Pluses.  Our IIci seems to be free from this type of clicking, or much
  450. less prone to it.  Could this be because the low level sound code is
  451. tailored to the ASC chip, and does not reliably leave the sound buffer clear
  452. on the older Macs (without ASC)?  
  453.  
  454. Back in the good ole days (pre-ASC, pre-Sound Mgr), I could eliminate all
  455. clicks by padding my waveforms to a multiple of the sound buffer size, and
  456. making sure to include a buffer's worth of zero samples at the end of every
  457. sound.  But I think that this trick does not work anymore. 
  458. -- 
  459. Julian Vrieslander 
  460. Neurobiology & Behavior, Mudd Hall, Cornell University, Ithaca NY 14853    
  461. INTERNET: eacj@theory.tc.cornell.edu     BITNET: eacj@crnlthry
  462. UUCP: ..cornell!batcomputer!eacj
  463.  
  464.  
  465.  
  466. - -------------------------
  467.  
  468. From: russotto@eng.umd.edu (Matthew T. Russotto)
  469. Subject:  Q: Eliminating clicks when playing sampled sounds
  470. Date: 27 Jan 92 15:24:03 GMT
  471. Organization: University of Maryland, College Park, College of Engineering
  472.  
  473. In article <1992Jan23.230559.25390@tc.cornell.edu> eacj@theory.TC.Cornell.EDU (Julian Vrieslander) writes:
  474.  
  475. >This recipe will eliminate one source of clicks, but it is still possible
  476. >to get clicks from another mechanism, at least on some Macs.
  477. >
  478. >I can create a long waveform containing *only* silent samples (0x80), and
  479. >when I play it repeatedly, sometimes there will be clicks produced.  If I
  480. >use Farallon's SoundEdit, the moving waveform cursor gives a rough indication
  481. >of where in the buffer the click is occurring.  I think it is usually at
  482. >the beginning of the buffer, but I am not certain that the clicks are
  483. >not coming at other points.  This clicking has been observed with several
  484. >programs, including some I wrote myself.  I use the simplest SoundMgr call:
  485. >SndPlay(NULL, theSnd, TRUE).   
  486. >
  487. >This clicking has been observed on our Mac II, and (I think) on our Mac
  488. >Pluses.  Our IIci seems to be free from this type of clicking, or much
  489. >less prone to it.  Could this be because the low level sound code is
  490. >tailored to the ASC chip, and does not reliably leave the sound buffer clear
  491. >on the older Macs (without ASC)?  
  492.  
  493. No, it can't be that simple:  The Mac II has the ASC.
  494. -- 
  495. Matthew T. Russotto    russotto@eng.umd.edu    russotto@wam.umd.edu
  496. Your superior intellect is no match for our puny weapons! -- The Simpsons
  497. Just say NO to police searches and seizures.  Make them use force.
  498. (not responsible for bodily harm resulting from following above advice)
  499.  
  500.  
  501.  
  502. - -------------------------
  503.  
  504. From: pwinkler@netcom.COM (Paul Winkler)
  505. Subject:  Q: Eliminating clicks when playing sampled sounds (conclusion)
  506. Date: 30 Jan 92 19:16:25 GMT
  507. Organization: Netcom - Online Communication Services  (408 241-9760 guest)
  508.  
  509.  
  510. A week or so ago, I posted a request for info on how to keep
  511. my application that uses sampled sound from generating clicks in 
  512. between groups of samples. My sound samples are imbedded in a disk
  513. file in groups of 800 bytes at a time, and was sampled at 8000 
  514. samples/sec (10 groups per second), and I need to play the data as 
  515. continuous sound.  I am running a Mac IIci and IIfx running 
  516. Sys 6.0.7.  I develop in MPW 3.2 and Think 5.0.
  517.  
  518. Thanks to the people who wrote or posted with suggestions, especially 
  519. Jim Reekes from Apple.  One more 'bravo' to the people in this group 
  520. and to the crew at Apple who take the time to support us here on 
  521. the 'net...
  522.  
  523. I wrote the test routines (included at the end of the post for your
  524. inspection) to find out what was going on, and how to solve my
  525. problem.  It plays sampled sounds and constant patterns.  It 
  526. generates a whole queue full of SoundHeaders and SndCommands
  527. at a time and then SndDoCommand's them in quick succession.
  528.  
  529. My conclusion is, that in order to get clickless audio (for sample
  530. rates in the 8kHz to 11kHz range that I tested), the sizes of the 
  531. buffers that you send to the Sound Manager in the 'bufferCmd's must
  532. be > 2K.  The 2048 bytes is the important number.  Send 2048 bytes 
  533. or less, and you get clicks, but if you send 2049 or more bytes at 
  534. a time, no clicks occur between groups of samples.
  535.  
  536. I also discovered a strange result.  If all the data samples are stored 
  537. contiguously in a large buffer, and SoundHeaders specifying
  538. small buffers are just pointed along it (using the samplePtr),
  539. then the 2K limit does *not* apply.  Moving the same data to separate
  540. buffers and pointing the SoundHeader's to them will have clicks if 
  541. they are <= 2K long.  Of course, if all the samples to play were 
  542. contiguous in memory to start, it would be pretty silly to break 
  543. them up into separate 'bufferCmds'...
  544.  
  545. All this probably has to do with the 2K RAM buffer on the ASC sound
  546. chip, and/or the Sound Manager's handling of it.
  547.  
  548. On to the code...  The code below will read samples from a file, or 
  549. generate a quiet tone (all 0x80's).  It will then generate and queue 
  550. a number of SoundHeaders and SndCommands based on the desired number of 
  551. samples to play at a time, and the total number of samples.
  552.  
  553. The code has #defines for testing a couple of the options I have 
  554. described.  The samples can be either in the 'sampleArea' field of 
  555. the SoundHeaders, in one contiguous buffer, or in separate buffers.
  556.  
  557. The routines are quick and dirty, so go easy on me please.  If there is 
  558. something you think I missed, (other than not Dispose'ing the buffers) 
  559. let me know however :).
  560.  
  561. So, my problem is solved, I just slap 3 of my 800 byte groups together
  562. (to make a 2400 byte buffer) before I call the Sound Manager...  Hope 
  563. this info was of help to someone...  Let me know...
  564.  
  565. Paul Winkler
  566. pwinkler@netcom.com
  567.  
  568. //
  569. // total number of samples to play in the constant value case
  570. //
  571. #define TOTAL_BYTES            (20*1024)
  572.  
  573. //
  574. // my 8KHz rate  (same results apply at the magic 11KHz too)
  575. //
  576. #define SAMP_RATE            0x1f400000L
  577.  
  578. //
  579. // This is the number of samples in one sound buffer 
  580. // (as specified by one SoundHeader and one SndCommand)
  581. // 
  582. // Note: if buffer size is 2048 or less (for sample rates up to 11K anyway)
  583. //     there will be audible 'clicks' between each buffer as they play
  584. //
  585. #define kBufferSize         (512)
  586.  
  587. //
  588. // another curious result:
  589. //    if you have all of your data in one long buffer, but break the 
  590. //    playing  of it up into pieces, the 2048 byte minimum above does 
  591. //    not apply
  592. //
  593. #define CONTIGUOUS 0
  594.  
  595. //
  596. // you can put the data in the sampleArea of the SoundHeader or in 
  597. // separate buffers.
  598. //
  599. #define DATA_IN_sampleArea 0
  600.  
  601. //
  602. // fill a buffer with audio samples from a file, or with a quiet pattern
  603. //
  604. Ptr
  605. fillSampBuf(long *size)
  606. {
  607.     Ptr            tmp,tmp1 ;
  608.     SFReply        reply ;
  609.     short        refNum ;
  610.     Point        where ;
  611.     long        eof ;
  612.     long    i;
  613.     
  614.     SetPt(&where, 100,100);
  615.     SFGetFile ( where, nil, nil, -1, nil, nil, &reply );
  616.     
  617.     if(reply.good) {
  618.         //
  619.         // user hit 'ok'...  read samples from the file into the buffer
  620.         // 
  621.         if((err = FSOpen(reply.fName,reply.vRefNum,&refNum)) != noErr)
  622.             doNote("\pFSOpen() err",err,10);
  623.         
  624.         if((err = GetEOF(refNum , &eof)) != noErr)
  625.             doNote("\pGetEOF() err",err,10) ;
  626.         
  627.         if((tmp = NewPtr( eof )) == nil)
  628.             doNote("\pNewPtr() err",MemError(),10) ;
  629.     
  630.         if((err = FSRead(refNum,&eof,tmp)) != noErr) 
  631.             doNote("\pFSRead() error",0,10);
  632.     
  633.         if((err = FSClose(refNum)) != noErr)
  634.             doNote("\pFSClose() error",0,10);
  635.  
  636.         *size = eof ;
  637.         return(tmp);
  638.     }
  639.     else {
  640.         //
  641.         // user hit 'cancel', fill the buffer with quiet
  642.         //
  643.         tmp = tmp1 = NewPtrClear( TOTAL_BYTES ) ;
  644.         
  645.         for(i = 0 ; i < TOTAL_BYTES ; i++) {
  646.             *tmp++ = 0x80 ;
  647.         }
  648.         *size = TOTAL_BYTES ;
  649.         return( tmp1 ) ;
  650.     }
  651. }
  652.  
  653. #if DATA_IN_sampleArea
  654.  
  655. typedef struct{
  656.     SoundHeader        hdr;
  657.     char            data[kBufferSize-1];
  658. } mySndHdr ;
  659.  
  660. #else
  661.  
  662. typedef struct{
  663.     SoundHeader        hdr;
  664. } mySndHdr ;
  665.  
  666. #endif
  667.  
  668. void
  669. doIt()
  670. {
  671.     SndChannelPtr    scp ;
  672.     mySndHdr    *shp ;
  673.     SndCommand    *cmd ;
  674.     SCStatus    status ;
  675.     short        i,j;
  676.     OSErr        err ;
  677.     Ptr        theData , tmp;
  678.     long        cnt,size ;
  679.     
  680.     /*
  681.      *    allocate the sound channel
  682.      */
  683.     scp = nil ;
  684.     if((err = SndNewChannel( &scp , sampledSynth , initMono , nil )) != noErr)
  685.         doNote("\pSndNewChannel() err",err,5) ;
  686.  
  687.     //
  688.     // read the samples from a file or generate a buffer 
  689.     // full of constant values (0x80's)
  690.     // size returns number of samples.
  691.     //
  692.     theData = fillSampBuf(&size) ;
  693.  
  694.     //
  695.     // cnt is number of buffers to break the sound into
  696.     // (may be leaving some samples out at the end, but who's counting?)
  697.     //
  698.     cnt = size / kBufferSize ;
  699.     
  700.     //
  701.     // allocate the space for all the SoundHeaders and SndCommands
  702.     //
  703.     if((shp = (mySndHdr *) NewPtr( cnt * sizeof(mySndHdr) )) == nil) {
  704.         doNote("\pNewPtr() err",MemError(),5) ;
  705.         return;
  706.     }
  707.     if((cmd = (SndCommand *) NewPtr( cnt * sizeof(SndCommand) )) == nil) {
  708.         doNote("\pNewPtr() err",MemError(),5) ;
  709.         return;
  710.     }
  711.     
  712.     //
  713.     // set up all the SoundHeaders and SndCommands
  714.     // so they can be queued in quick succession
  715.     // (no argument that the sound queue might have 
  716.     //  emptied to cause the clicking.)
  717.     //
  718.     for( i = 0 ; i < cnt ; i++ ) {
  719.  
  720. #if DATA_IN_sampleArea
  721.         //
  722.         // just like it says in IM
  723.         //
  724.         shp[i].hdr.samplePtr     = nil;
  725.  
  726.         //
  727.         // put one kBufferSize of the data into the 'sampleArea'[i]
  728.         //
  729.         for( j = 0 ; j < kBufferSize ; j++) 
  730.             shp[i].hdr.sampleArea[j] = *theData++ ;
  731. #else
  732.  
  733. #if CONTIGUOUS
  734.         //
  735.         // point subsequent 'SoundHeader's to subsequent parts
  736.         // of the contiguous sampled data buffer
  737.         //
  738.         shp[i].hdr.samplePtr     = theData ;
  739.         theData += kBufferSize ;
  740. #else        
  741.         //
  742.         //    the other option is to allocate discontiguous buffers
  743.         //  and copy data into them 
  744.         //
  745.         if((tmp = shp[i].hdr.samplePtr = NewPtr( kBufferSize )) == nil) {
  746.             doNote("\pNewPtr() err",MemError(),5) ;
  747.             return;
  748.         }
  749.         for( j = 0 ; j < kBufferSize ; j++) 
  750.             *tmp++ = *theData++ ;
  751. #endif
  752.  
  753. #endif
  754.         shp[i].hdr.length    = kBufferSize ;
  755.         shp[i].hdr.sampleRate    = SAMP_RATE ;
  756.         shp[i].hdr.loopStart    = 0 ;
  757.         shp[i].hdr.loopEnd    = 0 ;
  758.         shp[i].hdr.encode    = stdSH ;
  759.         shp[i].hdr.baseFrequency = 60 ;
  760.  
  761.         //
  762.         // set up the SndCommand for this buffer of samples
  763.         //
  764.         cmd[i].cmd    = bufferCmd ;
  765.         cmd[i].param1    = 0 ;
  766.         cmd[i].param2    = (long)&shp[i] ;
  767.     }
  768.  
  769.     //
  770.     // fill up the queue for the channel 
  771.     //
  772.     for( i = 0 ; i < 127 ; i++ ) {
  773.         if((err = SndDoCommand( scp , &cmd[i] , true)) != noErr)
  774.             doNote("\pSndDoCommand() err",err,5) ;
  775.     }
  776.  
  777.     while( !Button() ) ;        // wait for the sound to finish
  778.     
  779.     if((err = SndDisposeChannel( scp , false )) != noErr )
  780.         doNote("\pSndDisposeChannel() err",err,5) ;
  781. }
  782.  
  783. /* -- eof -- */
  784.  
  785.  
  786.  
  787. - -------------------------
  788.  
  789. From: pwinkler@netcom.COM (Paul Winkler)
  790. Subject:  Q: Eliminating clicks when playing sampled sounds (conclusion)
  791. Date: 30 Jan 92 19:16:25 GMT
  792. Organization: Netcom - Online Communication Services  (408 241-9760 guest)
  793.  
  794.  
  795. A week or so ago, I posted a request for info on how to keep
  796. my application that uses sampled sound from generating clicks in 
  797. between groups of samples. My sound samples are imbedded in a disk
  798. file in groups of 800 bytes at a time, and was sampled at 8000 
  799. samples/sec (10 groups per second), and I need to play the data as 
  800. continuous sound.  I am running a Mac IIci and IIfx running 
  801. Sys 6.0.7.  I develop in MPW 3.2 and Think 5.0.
  802.  
  803. Thanks to the people who wrote or posted with suggestions, especially 
  804. Jim Reekes from Apple.  One more 'bravo' to the people in this group 
  805. and to the crew at Apple who take the time to support us here on 
  806. the 'net...
  807.  
  808. I wrote the test routines (included at the end of the post for your
  809. inspection) to find out what was going on, and how to solve my
  810. problem.  It plays sampled sounds and constant patterns.  It 
  811. generates a whole queue full of SoundHeaders and SndCommands
  812. at a time and then SndDoCommand's them in quick succession.
  813.  
  814. My conclusion is, that in order to get clickless audio (for sample
  815. rates in the 8kHz to 11kHz range that I tested), the sizes of the 
  816. buffers that you send to the Sound Manager in the 'bufferCmd's must
  817. be > 2K.  The 2048 bytes is the important number.  Send 2048 bytes 
  818. or less, and you get clicks, but if you send 2049 or more bytes at 
  819. a time, no clicks occur between groups of samples.
  820.  
  821. I also discovered a strange result.  If all the data samples are stored 
  822. contiguously in a large buffer, and SoundHeaders specifying
  823. small buffers are just pointed along it (using the samplePtr),
  824. then the 2K limit does *not* apply.  Moving the same data to separate
  825. buffers and pointing the SoundHeader's to them will have clicks if 
  826. they are <= 2K long.  Of course, if all the samples to play were 
  827. contiguous in memory to start, it would be pretty silly to break 
  828. them up into separate 'bufferCmds'...
  829.  
  830. All this probably has to do with the 2K RAM buffer on the ASC sound
  831. chip, and/or the Sound Manager's handling of it.
  832.  
  833. On to the code...  The code below will read samples from a file, or 
  834. generate a quiet tone (all 0x80's).  It will then generate and queue 
  835. a number of SoundHeaders and SndCommands based on the desired number of 
  836. samples to play at a time, and the total number of samples.
  837.  
  838. The code has #defines for testing a couple of the options I have 
  839. described.  The samples can be either in the 'sampleArea' field of 
  840. the SoundHeaders, in one contiguous buffer, or in separate buffers.
  841.  
  842. The routines are quick and dirty, so go easy on me please.  If there is 
  843. something you think I missed, (other than not Dispose'ing the buffers) 
  844. let me know however :).
  845.  
  846. So, my problem is solved, I just slap 3 of my 800 byte groups together
  847. (to make a 2400 byte buffer) before I call the Sound Manager...  Hope 
  848. this info was of help to someone...  Let me know...
  849.  
  850. Paul Winkler
  851. pwinkler@netcom.com
  852.  
  853. //
  854. // total number of samples to play in the constant value case
  855. //
  856. #define TOTAL_BYTES            (20*1024)
  857.  
  858. //
  859. // my 8KHz rate  (same results apply at the magic 11KHz too)
  860. //
  861. #define SAMP_RATE            0x1f400000L
  862.  
  863. //
  864. // This is the number of samples in one sound buffer 
  865. // (as specified by one SoundHeader and one SndCommand)
  866. // 
  867. // Note: if buffer size is 2048 or less (for sample rates up to 11K anyway)
  868. //     there will be audible 'clicks' between each buffer as they play
  869. //
  870. #define kBufferSize         (512)
  871.  
  872. //
  873. // another curious result:
  874. //    if you have all of your data in one long buffer, but break the 
  875. //    playing  of it up into pieces, the 2048 byte minimum above does 
  876. //    not apply
  877. //
  878. #define CONTIGUOUS 0
  879.  
  880. //
  881. // you can put the data in the sampleArea of the SoundHeader or in 
  882. // separate buffers.
  883. //
  884. #define DATA_IN_sampleArea 0
  885.  
  886. //
  887. // fill a buffer with audio samples from a file, or with a quiet pattern
  888. //
  889. Ptr
  890. fillSampBuf(long *size)
  891. {
  892.     Ptr            tmp,tmp1 ;
  893.     SFReply        reply ;
  894.     short        refNum ;
  895.     Point        where ;
  896.     long        eof ;
  897.     long    i;
  898.     
  899.     SetPt(&where, 100,100);
  900.     SFGetFile ( where, nil, nil, -1, nil, nil, &reply );
  901.     
  902.     if(reply.good) {
  903.         //
  904.         // user hit 'ok'...  read samples from the file into the buffer
  905.         // 
  906.         if((err = FSOpen(reply.fName,reply.vRefNum,&refNum)) != noErr)
  907.             doNote("\pFSOpen() err",err,10);
  908.         
  909.         if((err = GetEOF(refNum , &eof)) != noErr)
  910.             doNote("\pGetEOF() err",err,10) ;
  911.         
  912.         if((tmp = NewPtr( eof )) == nil)
  913.             doNote("\pNewPtr() err",MemError(),10) ;
  914.     
  915.         if((err = FSRead(refNum,&eof,tmp)) != noErr) 
  916.             doNote("\pFSRead() error",0,10);
  917.     
  918.         if((err = FSClose(refNum)) != noErr)
  919.             doNote("\pFSClose() error",0,10);
  920.  
  921.         *size = eof ;
  922.         return(tmp);
  923.     }
  924.     else {
  925.         //
  926.         // user hit 'cancel', fill the buffer with quiet
  927.         //
  928.         tmp = tmp1 = NewPtrClear( TOTAL_BYTES ) ;
  929.         
  930.         for(i = 0 ; i < TOTAL_BYTES ; i++) {
  931.             *tmp++ = 0x80 ;
  932.         }
  933.         *size = TOTAL_BYTES ;
  934.         return( tmp1 ) ;
  935.     }
  936. }
  937.  
  938. #if DATA_IN_sampleArea
  939.  
  940. typedef struct{
  941.     SoundHeader        hdr;
  942.     char            data[kBufferSize-1];
  943. } mySndHdr ;
  944.  
  945. #else
  946.  
  947. typedef struct{
  948.     SoundHeader        hdr;
  949. } mySndHdr ;
  950.  
  951. #endif
  952.  
  953. void
  954. doIt()
  955. {
  956.     SndChannelPtr    scp ;
  957.     mySndHdr    *shp ;
  958.     SndCommand    *cmd ;
  959.     SCStatus    status ;
  960.     short        i,j;
  961.     OSErr        err ;
  962.     Ptr        theData , tmp;
  963.     long        cnt,size ;
  964.     
  965.     /*
  966.      *    allocate the sound channel
  967.      */
  968.     scp = nil ;
  969.     if((err = SndNewChannel( &scp , sampledSynth , initMono , nil )) != noErr)
  970.         doNote("\pSndNewChannel() err",err,5) ;
  971.  
  972.     //
  973.     // read the samples from a file or generate a buffer 
  974.     // full of constant values (0x80's)
  975.     // size returns number of samples.
  976.     //
  977.     theData = fillSampBuf(&size) ;
  978.  
  979.     //
  980.     // cnt is number of buffers to break the sound into
  981.     // (may be leaving some samples out at the end, but who's counting?)
  982.     //
  983.     cnt = size / kBufferSize ;
  984.     
  985.     //
  986.     // allocate the space for all the SoundHeaders and SndCommands
  987.     //
  988.     if((shp = (mySndHdr *) NewPtr( cnt * sizeof(mySndHdr) )) == nil) {
  989.         doNote("\pNewPtr() err",MemError(),5) ;
  990.         return;
  991.     }
  992.     if((cmd = (SndCommand *) NewPtr( cnt * sizeof(SndCommand) )) == nil) {
  993.         doNote("\pNewPtr() err",MemError(),5) ;
  994.         return;
  995.     }
  996.     
  997.     //
  998.     // set up all the SoundHeaders and SndCommands
  999.     // so they can be queued in quick succession
  1000.     // (no argument that the sound queue might have 
  1001.     //  emptied to cause the clicking.)
  1002.     //
  1003.     for( i = 0 ; i < cnt ; i++ ) {
  1004.  
  1005. #if DATA_IN_sampleArea
  1006.         //
  1007.         // just like it says in IM
  1008.         //
  1009.         shp[i].hdr.samplePtr     = nil;
  1010.  
  1011.         //
  1012.         // put one kBufferSize of the data into the 'sampleArea'[i]
  1013.         //
  1014.         for( j = 0 ; j < kBufferSize ; j++) 
  1015.             shp[i].hdr.sampleArea[j] = *theData++ ;
  1016. #else
  1017.  
  1018. #if CONTIGUOUS
  1019.         //
  1020.         // point subsequent 'SoundHeader's to subsequent parts
  1021.         // of the contiguous sampled data buffer
  1022.         //
  1023.         shp[i].hdr.samplePtr     = theData ;
  1024.         theData += kBufferSize ;
  1025. #else        
  1026.         //
  1027.         //    the other option is to allocate discontiguous buffers
  1028.         //  and copy data into them 
  1029.         //
  1030.         if((tmp = shp[i].hdr.samplePtr = NewPtr( kBufferSize )) == nil) {
  1031.             doNote("\pNewPtr() err",MemError(),5) ;
  1032.             return;
  1033.         }
  1034.         for( j = 0 ; j < kBufferSize ; j++) 
  1035.             *tmp++ = *theData++ ;
  1036. #endif
  1037.  
  1038. #endif
  1039.         shp[i].hdr.length    = kBufferSize ;
  1040.         shp[i].hdr.sampleRate    = SAMP_RATE ;
  1041.         shp[i].hdr.loopStart    = 0 ;
  1042.         shp[i].hdr.loopEnd    = 0 ;
  1043.         shp[i].hdr.encode    = stdSH ;
  1044.         shp[i].hdr.baseFrequency = 60 ;
  1045.  
  1046.         //
  1047.         // set up the SndCommand for this buffer of samples
  1048.         //
  1049.         cmd[i].cmd    = bufferCmd ;
  1050.         cmd[i].param1    = 0 ;
  1051.         cmd[i].param2    = (long)&shp[i] ;
  1052.     }
  1053.  
  1054.     //
  1055.     // fill up the queue for the channel 
  1056.     //
  1057.     for( i = 0 ; i < 127 ; i++ ) {
  1058.         if((err = SndDoCommand( scp , &cmd[i] , true)) != noErr)
  1059.             doNote("\pSndDoCommand() err",err,5) ;
  1060.     }
  1061.  
  1062.     while( !Button() ) ;        // wait for the sound to finish
  1063.     
  1064.     if((err = SndDisposeChannel( scp , false )) != noErr )
  1065.         doNote("\pSndDisposeChannel() err",err,5) ;
  1066. }
  1067.  
  1068. /* -- eof -- */
  1069.  
  1070.  
  1071.  
  1072. ---------------------------
  1073.  
  1074. From: williamu@extro.ucc.su.OZ.AU (William Uther)
  1075. Subject: Software Locking for Word 4D
  1076. Date: 18 Feb 92 04:09:06 GMT
  1077. Organization: Uni Computing Service, Uni of Sydney, Australia
  1078.  
  1079. Hi,
  1080.   I am in charge on two Mac SE's at college with which most people use word 4.
  1081. The college owns some copies of word to use with these mac's, but the Mac's
  1082. are unsupervised and there is a problem with the disks being stolen or trashed.
  1083. The best solution for this would be to give each user there own copies of the
  1084. system and word disks, but this would breach copywrite.
  1085.   I was wondering if it would be possable to put a small piece of code into
  1086. the word programs which checked the serial number of the mac it was running
  1087. on and would exit if it wasn't one of the allowed mac's.  This probably breaches
  1088. the letter of the licence aggreement, but it is to preserve the spirit of the
  1089. aggreement and stop copies.
  1090.   Anyone have any idea's.  Maybe a writer of virus's could do something useful
  1091. and help out??
  1092.   Thanks in advance
  1093.                             \x/ill                    :-}
  1094.  
  1095.  
  1096.  
  1097. - -------------------------
  1098.  
  1099. From: Carl.Constantine@BCSystems.GOV.BC.CA
  1100. Subject:  Software Locking for Word 4D
  1101. Date: 19 Feb 92 23:59:53 GMT
  1102. Organization: BC Systems Corporation
  1103.  
  1104. In article <1992Feb18.040906.3763@ucc.su.OZ.AU>, williamu@extro.ucc.su.OZ.AU (William Uther) writes:
  1105. > Hi,
  1106. >   I am in charge on two Mac SE's at college with which most people use word 4.
  1107. > The college owns some copies of word to use with these mac's, but the Mac's
  1108. > are unsupervised and there is a problem with the disks being stolen or trashed.
  1109. > The best solution for this would be to give each user there own copies of the
  1110. > system and word disks, but this would breach copywrite.
  1111. >   I was wondering if it would be possable to put a small piece of code into
  1112. > the word programs which checked the serial number of the mac it was running
  1113. > on and would exit if it wasn't one of the allowed mac's.  This probably breaches
  1114. > the letter of the licence aggreement, but it is to preserve the spirit of the
  1115. > aggreement and stop copies.
  1116. >   Anyone have any idea's.  Maybe a writer of virus's could do something useful
  1117. > and help out??
  1118. >   Thanks in advance
  1119. >                             \x/ill                    :-}
  1120.  
  1121. Actually, you could write this program yourself, use ResEdit to make Word 4
  1122. invisible on the distrutable diskette and give your program the creater types
  1123. etc of Word.  This actually prevents users from copying Word to becase they get
  1124. your probram and not the _invisible_ Word file.  This is what we use to do at
  1125. UVic (University of Victoria in British Columbia) before the Server went in.
  1126. good luck.
  1127. -- 
  1128. Carl.Constantine@BCSystems.gov.bc.ca
  1129. Victoria, British Columbia, Canada
  1130.  
  1131.  
  1132.  
  1133. ---------------------------
  1134.  
  1135. From: dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz)
  1136. Subject: DirectorOwner owns DialogDirector and crashes (Think C/TCL)
  1137. Date: 19 Feb 92 04:43:24 GMT
  1138. Organization: University of Illinois at Urbana
  1139.  
  1140. I am trying to implement an application in Think C 5.0.2 and TCL
  1141. 1.1.2.  I want my documents to control modal dialogs instead of
  1142. regular windows.  Everything works fine, except when I dispose of the
  1143. dialog, I crash.
  1144.  
  1145. I traced it throught the debugger, and hear is what happens:
  1146.  
  1147. (1) CDocument is a subclass of CDirectorOwner.
  1148. (2) CDialogDirector is a subclass of CDirector.
  1149. (3) When myDialogDirector is initialized with myDocument as its
  1150.     supervisor, myDialogDirector is installed on the list of directors
  1151.     owned by myDocument (this is done in the IDirector() method).
  1152. (4) myDialogDirector is the only director owned by myDocument.
  1153. (5) When I dispose of myDialogDirector, myDocument's list of directors
  1154.     that it owns becomes empty.
  1155. (6) This happens just before myDialogDirector actual gets disposed.
  1156. (7) Also before myDialogDirector gets disposed, myDocument finds its
  1157.     list of directors empty, so being the good CDirectorOwner that it
  1158.     is (with no more directors to look after), it disposes of itself.
  1159. (8) Now, myDialogDirector is about to actually dispose of itself, but
  1160.     itsSupervisor (myDocument) has just been disposed.
  1161. (9) When myDialogDirector actually disposes of itself, it finds that
  1162.     it is the gopher.  Therefore, it makes itsSupervisor the gopher.
  1163.     itsSupervisor->BecomeGopher(TRUE)
  1164. (10) However, itsSupervisor (i.e., myDocument) was already disposed
  1165.      (in step 7) so BANG!!!! The program crashes.
  1166.  
  1167. This was all done with TCL code.  I just asked for myDialog to be
  1168. supervised by myDocument.  Then, later, I asked for myDialog to be
  1169. disposed.  (If I don't dispose of myDialog, TCL will do it for me and
  1170. crash anyway.)  This seems to be a bug in TCL.  Is it?  If it isn't,
  1171. what am I doing wrong?
  1172.  
  1173. I can work around this problem by installing a dummyDirector with
  1174. myDocument as itsSupervisor.  This means that myDocument never finds
  1175. its list directors that it owns empty so it doesn't dispose of itself.
  1176. This is really a kluge so there must be a better way.  What is it?
  1177.  
  1178. Thanks for your help.
  1179. -- 
  1180. David M. Marcovitz                     |  internet: marcovitz@uiuc.edu
  1181. Computer-based Education Research Lab  |            dmmg1176@uxa.cso.uiuc.edu
  1182. University of Illinois                 |  novanet:  marco / cca / nova
  1183.  
  1184.  
  1185.  
  1186. - -------------------------
  1187.  
  1188. From: dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz)
  1189. Subject:  DirectorOwner owns DialogDirector and crashes (Think C/TCL)
  1190. Organization: University of Illinois at Urbana
  1191. Date: Wed, 19 Feb 1992 17:56:36 GMT
  1192.  
  1193. dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz) writes:
  1194.  
  1195. >I am trying to implement an application in Think C 5.0.2 and TCL
  1196. >1.1.2.  I want my documents to control modal dialogs instead of
  1197. >regular windows.  Everything works fine, except when I dispose of the
  1198. >dialog, I crash.
  1199.  
  1200. >...stuff deleted...
  1201.  
  1202. >I can work around this problem by installing a dummyDirector with
  1203. >myDocument as itsSupervisor.  This means that myDocument never finds
  1204. >its list directors that it owns empty so it doesn't dispose of itself.
  1205. >This is really a kluge so there must be a better way.  What is it?
  1206.  
  1207. Another thing that seems to work is if I make myDocument the gopher
  1208. before disposing of myDialogDirector.  Then, myDialogDirector doesn't
  1209. need to make myDocument (itsSupervisor) gopher just before disposing
  1210. of itself.  This is less of a kluge, but there still must be a better
  1211. way.
  1212.  
  1213. -- 
  1214. David M. Marcovitz                     |  internet: marcovitz@uiuc.edu
  1215. Computer-based Education Research Lab  |            dmmg1176@uxa.cso.uiuc.edu
  1216. University of Illinois                 |  novanet:  marco / cca / nova
  1217.  
  1218.  
  1219.  
  1220. - -------------------------
  1221.  
  1222. From: rla20@duts.ccc.amdahl.com (Roger Allen)
  1223. Subject:  DirectorOwner owns DialogDirector and crashes (Think C/TCL)
  1224. Date: 19 Feb 92 19:37:39 GMT
  1225. Organization: Amdahl Corporation, Sunnyvale CA
  1226.  
  1227. In article <1992Feb19.175636.19560@ux1.cso.uiuc.edu> dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz) writes:
  1228. >dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz) writes:
  1229. >
  1230. >>I am trying to implement an application in Think C 5.0.2 and TCL
  1231. >>1.1.2.  I want my documents to control modal dialogs instead of
  1232. >>regular windows.  Everything works fine, except when I dispose of the
  1233. >>dialog, I crash.
  1234. >
  1235. ...stuff deleted...
  1236. >Another thing that seems to work is if I make myDocument the gopher
  1237. >before disposing of myDialogDirector.  Then, myDialogDirector doesn't
  1238. >need to make myDocument (itsSupervisor) gopher just before disposing
  1239. >of itself.  This is less of a kluge, but there still must be a better
  1240. >way.
  1241.  
  1242. Why is this a kludge?  Seems like the document should keep track of its
  1243. gophers.  Where should the gopher point to after you get rid of the
  1244. current object it is pointing to?  Doesn`t seem like a kludge--seems
  1245. like proper housekeeping.
  1246.  
  1247. Just my 2cents.
  1248. --
  1249. > Roger Allen                   |  All the opinions expressed are my     <
  1250. > Amdahl Computer Development   |  own and are not Amdahl's.             <
  1251. > rla20@cd.amdahl.com           |  ------They paid me to say that------- <
  1252.  
  1253.  
  1254.  
  1255. - -------------------------
  1256.  
  1257. From: dmmg1176@uxa.cso.uiuc.edu (David M Marcovitz)
  1258. Subject:  DirectorOwner owns DialogDirector and crashes (Think C/TCL)
  1259. Date: 19 Feb 92 22:52:53 GMT
  1260. Organization: University of Illinois at Urbana
  1261.  
  1262. rla20@duts.ccc.amdahl.com (Roger Allen) writes:
  1263. >Why is this a kludge?  Seems like the document should keep track of its
  1264. >gophers.  Where should the gopher point to after you get rid of the
  1265. >current object it is pointing to?  Doesn`t seem like a kludge--seems
  1266. >like proper housekeeping.
  1267.  
  1268. The reason this is a kludge is that TCL does this for me, sort of.
  1269. When TCL disposes of myDialogDirector, it checks to see if it is the
  1270. gopher, and if it is, it makes itsSupervisor (myDocument) the gopher.
  1271. Unfortunately, it has already disposed of myDocument.  It shouldn't
  1272. dispose of myDocument until AFTER it finishes disposing of
  1273. myDialogDirector.
  1274.  
  1275. -- 
  1276. David M. Marcovitz                     |  internet: marcovitz@uiuc.edu
  1277. Computer-based Education Research Lab  |            dmmg1176@uxa.cso.uiuc.edu
  1278. University of Illinois                 |  novanet:  marco / cca / nova
  1279.  
  1280.  
  1281.  
  1282. ---------------------------
  1283.  
  1284. End of C.S.M.P. Digest
  1285. **********************
  1286.